package com.example.demo.config;


import com.example.demo.common.AjaxResult;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 *  实现 统一数据格式返回 的保底类.
 *  (避免没有调用 AjaxResult 中的返回数据的方法)
 *  说明: 在返回数据之前, 检查数据的类型是否为统一的对象, 如果不是, 封装为统一对象再返回.
 */
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {

    /**
     * 是一个开关, 返回 true 才会调用 beforeBodyWrite 方法.
     */
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }

    /**
     * 对数据格式进行校验和封装.
     */
    @Autowired
    private ObjectMapper objectMapper; // 可以提供 String 类型转为 json 的 ajax 对象 的方法.
    @SneakyThrows
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                  Class selectedConverterType, ServerHttpRequest request,
                                  ServerHttpResponse response) {
        // 返回的信息就是 AjaxResult 对象, 不做处理
        if (body instanceof AjaxResult)
            return body;
        // 返回的信息是 String 类型, 将其转换为 json 格式返回.
        if (body instanceof String)
            return objectMapper.writeValueAsString(body);
        // 除了上述两种特殊情况, 就封装为 AjaxResult 类型进行返回.
        return AjaxResult.success(body);
    }
}

